/*****************************************************************************************************
*       SRLOS Team
*@filename:     k_head.c
*@brief   :     this file is the "C" language code header!
*@author  :     bloceanc
*@note    :
*@comment :
*@datetime:     24/04/2010 21:26:33
*****************************************************************************************************/
#ifndef _K_HEAD_C_
#define _K_HEAD_C_

#include "./mem/mem_basedefine.h"
#include "k_common_asm.h"

/**
 * System interrupt vector table
 */
typedef struct tag_kernel_interrupt_vector{
	unsigned int reset_handle;					// reset interrupt
	unsigned int undef_handle;					// undefine instruction interrupt
	unsigned int swi_handle;					// Software Interrupt
	unsigned int prefetch_handle;				// Prefetch Interrupt
	unsigned int dataabort_handle;				// data abort interrupt
	unsigned int reserved_handle;				// reseved interrupt vecotr!
	unsigned int irq_handle;					// IRQ interrupt
	unsigned int fiq_handle;					// FIQ interrupt
}K_INT_VectorTable;

/** memory initialize */
extern void k_mem_phy_init(unsigned int ram_phy_startaddr, unsigned int ram_phy_endaddr);
extern void k_mem_mmu_initialize();

/** CP15 control, MMU */
extern void k_cp15_c1_MMU_enablish(unsigned int b);
extern void k_cp15_c2_write_flpt(unsigned int phy_addr);
extern void k_cp5_c1_ICache_enablish(unsigned int b);
extern void k_cp5_c1_DCache_enablish(unsigned int b);

/** interrupt handler */
extern unsigned int g_interrupt_data_abt;
extern unsigned int g_interrupt_instr_abt;
extern unsigned int g_interrupt_fiq;
extern unsigned int g_interrupt_irq;
extern unsigned int g_interrupt_reset;
extern unsigned int g_interrupt_svc;
extern unsigned int g_interrupt_und;

/** OS MMU temp base address */
extern unsigned int k_mem_mmu_flpt_os_tmp;
extern unsigned int k_mem_mmu_slpt_os_tmp;

/** OS I/O mapping second level page table temp address */
extern unsigned int k_mem_mmu_slpt_io_mapping_tmp;

/*----------------------------------------------------------*/

/** OS MMU loaded base address */
unsigned int k_mem_mmu_flpt_os;
unsigned int k_mem_mmu_slpt_os;

/** OS I/O mapping second level page table loaded address */
unsigned int k_mem_mmu_slpt_io_mapping;

/**
 * @BRIEF	:	Initialize Initalize System
 * @PARAM	:	void
 * @RETURN	:	void
 */
void k_os_start(void)
{
	unsigned int i;
	unsigned int *start_addr = 0x0;
	unsigned int nsize = K_SYS_SIZE << 12;
	unsigned int *ram_start_addr = (unsigned int *)K_SYS_RAM_START_ADDR;
	unsigned int ram_size = K_VAL_MAXMEMSIZE << 20;
	unsigned int copy_time = nsize >> 2;		// copy by 4B every times
	K_INT_VectorTable	*int_vt = 0;

	// close interrupt.
	K_MEM_DISABLE_INTERRUPT;

	// first copy self to the RAM
	for(i = 0; i < copy_time; i++)
	{
		*(ram_start_addr + i) = *(start_addr + i);
	}

	// modify os flpt and slpt!
	k_mem_mmu_flpt_os = k_mem_mmu_flpt_os_tmp + K_SYS_RAM_START_ADDR;
	k_mem_mmu_slpt_os = k_mem_mmu_slpt_os_tmp + K_SYS_RAM_START_ADDR;
	k_mem_mmu_slpt_io_mapping = k_mem_mmu_slpt_io_mapping_tmp + K_SYS_RAM_START_ADDR;

	// second initialize physical memory
	k_mem_phy_init((unsigned int)ram_start_addr, ((unsigned int)ram_start_addr) + ram_size);

	// initialize mmu management
	k_mem_mmu_initialize();

	// enable MMU
	k_cp15_c2_write_flpt(k_mem_mmu_flpt_os);
	k_cp5_c1_ICache_enablish(1);
	k_cp5_c1_DCache_enablish(1);
	k_cp15_c1_MMU_enablish(1);

	// initialize interrupt handle=> this must be after MMU enabled!
	int_vt->fiq_handle			=	g_interrupt_fiq;
	int_vt->dataabort_handle	=	g_interrupt_data_abt;
	int_vt->irq_handle			= 	g_interrupt_irq;
	int_vt->swi_handle			= 	g_interrupt_svc;
	int_vt->undef_handle		= 	g_interrupt_und;
	int_vt->reset_handle		=	g_interrupt_reset;
	int_vt->prefetch_handle		=	g_interrupt_instr_abt;

	// enable interrupt
	K_MEM_ENABLE_INTERRUPT;

	// now, we just loop NULL
	while(1);
}

#endif /* _K_HEAD_C_ */
